﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using DcsGauges.Gui.Rendering.Interfaces;
using Microsoft.Xna.Framework.Input;
using DcsGauges.Input.Events;

namespace DcsGauges.Input.Mouse
{
    class MouseEventDispatcher
    {
        public IGuiRenderable GuiRoot { get; set; }


        private MouseState                  lastState                   = new MouseState();


        public void Update(GameTime gt)
        {
            MouseState ms       = Microsoft.Xna.Framework.Input.Mouse.GetState();

            if (this.GuiRoot != null)
            {
                
                int         dx      = 0;
                int         dy      = 0;

                foreach (MouseEvent.MouseButtons btn in Enum.GetValues(typeof(MouseEvent.MouseButtons)))
                { 
                    if (this.IsMouseDown(ms, btn) == true)
                    {
                        this.GuiRoot.InjectMouseEvent(new Events.MouseEvent(Events.MouseEvent.EventTypes.MouseDown, btn, new Point(ms.X, ms.Y)), gt);
                    }
                    else if (this.IsMouseUp(ms, btn) == true)
                    {
                        this.GuiRoot.InjectMouseEvent(new Events.MouseEvent(Events.MouseEvent.EventTypes.MouseUp, btn, new Point(ms.X, ms.Y)), gt);
                    }
                }

                if (this.MouseMoved(ms, out dx, out dy) == true)
                {
                    MouseEvent.MouseButtons buttons = MouseEvent.MouseButtons.None;
                    
                    if(ms.LeftButton    == ButtonState.Pressed) buttons |= MouseEvent.MouseButtons.Left;
                    if(ms.MiddleButton  == ButtonState.Pressed) buttons |= MouseEvent.MouseButtons.Middle;
                    if(ms.MiddleButton  == ButtonState.Pressed) buttons |= MouseEvent.MouseButtons.Right;

                    this.GuiRoot.InjectMouseEvent(new MouseEvent(MouseEvent.EventTypes.MouseMove, buttons, new Point(ms.X, ms.Y), dx, dy), gt);
                }
            }

            this.lastState = ms;
        }


        private bool IsMouseDown(MouseState currentState, MouseEvent.MouseButtons button)
        {
            switch(button)
            {
                case MouseEvent.MouseButtons.Left:  return this.lastState.LeftButton == ButtonState.Released && currentState.LeftButton == ButtonState.Pressed;
                case MouseEvent.MouseButtons.Middle: return this.lastState.MiddleButton == ButtonState.Released && currentState.MiddleButton == ButtonState.Pressed;
                case MouseEvent.MouseButtons.Right: return this.lastState.RightButton == ButtonState.Released && currentState.RightButton == ButtonState.Pressed;
            }

            return false;
        }

        private bool IsMouseUp(MouseState currentState, MouseEvent.MouseButtons button)
        {
            switch(button)
            {
                case MouseEvent.MouseButtons.Left:  return this.lastState.LeftButton == ButtonState.Pressed && currentState.LeftButton == ButtonState.Released;
                case MouseEvent.MouseButtons.Middle: return this.lastState.MiddleButton == ButtonState.Pressed && currentState.MiddleButton == ButtonState.Released;
                case MouseEvent.MouseButtons.Right: return this.lastState.RightButton == ButtonState.Pressed && currentState.RightButton == ButtonState.Released;
            }

            return false;
        }

        private bool MouseMoved(MouseState currentState, out int dx, out int dy)
        {
            bool result     = this.lastState.X != currentState.X || this.lastState.Y != currentState.Y;
            dx              = currentState.X - this.lastState.X;
            dy              = currentState.Y - this.lastState.Y;
            return result;
        }
    }
}
